/* 
 * File:   RapidHttpServlet.cpp
 * Author: dell
 * 
 * Created on 2012年4月2日, 下午6:20
 */

#include "RapidHttpServlet.h"
#include <cerrno>
#include <string>
#include <evhttp/HttpHandler.h>
#include <evhttp/Process.h>
#include <evhttp/HttpProcess.h>

using namespace std;

namespace Rapid{
    RapidHttpServlet::RapidHttpServlet(ServerConfig* serverConfig, ContextConfig* contextConfig, const char* subpath):
        fileCached(serverConfig), serverConfig(serverConfig), contextConfig(contextConfig), subpath(subpath), file()
    {

    }


    RapidHttpServlet::~RapidHttpServlet() {
        if(file.fd > 0){
            ::close(file.fd);
        }
    }


    void RapidHttpServlet::service(Request& req, Response& resp){
        LOG_DEBUG("root:%s, subpath:%s, subpath.size():%d", contextConfig->name.c_str(), subpath, strlen(subpath));
        LOG_DEBUG("docBase:%s", contextConfig->docBase.c_str());

        if(strlen(subpath) == 0){
            //返回默认页面
            openWelcomeFile();
        }else{
            //请求的文件
            openRequestFile();
        }
        if(file.fd <= 0){
            //文件不存在
            resp.setStatus(400, string("file not exist, name is ").append(file.filename).c_str());
            return;
        }

        ContentTypeConfig* contentTypeConfig = getContentTypeConfig(getExpandName(&file.filename));
        if(contentTypeConfig){
            //设置默认响应头
            std::vector<const char*> headerNames;
            contentTypeConfig->headers.getNames(headerNames);
            std::vector<const char*>::iterator nameit = headerNames.begin();
            for(; nameit != headerNames.end(); nameit++){
                const ContentTypeConfig::Headers::Value* headerValue = contentTypeConfig->headers.gets(*nameit);
                do{
                    LOG_DEBUG("header name:%s, value:%s", *nameit, headerValue->text);
                    resp.addHeader(*nameit, headerValue->text);
                }while(headerValue = headerValue->next);
            }

            //设置内容类型
            resp.setContentType(contentTypeConfig->contentType.c_str());
        }else{
            resp.setContentType("application/octet-stream");
        }

        //设置内容长度
        resp.setContentLength(file.stat.st_size);    

        //向客户端传输文件
        resp.sendfile(file.fd, 0, file.stat.st_size, contextConfig->maxSpeed, SEND_SIZE);
    }


//    bool RapidHttpServlet::onCompletionEvent(){
//        LOG_DEBUG("");
//        return true;
//    }
//
//    bool RapidHttpServlet::onWriteQueueEmptyEvent(){
//        LOG_DEBUG("");
//        return true;
//    }    

    //返回可用的欢迎页
    void RapidHttpServlet::openWelcomeFile(){
        std::vector<const char*>::iterator wfileit = contextConfig->welcomeFiles.begin();
        for(; wfileit != contextConfig->welcomeFiles.end(); wfileit++){
            file.filename.clear();
            file.physicalFilename.clear();        
            file.filename.append(subpath).append("/").append(*wfileit);
            file.physicalFilename.append(contextConfig->docBase).append(file.filename);
            LOG_DEBUG("file.physicalFilename:%s", file.physicalFilename.c_str());
            openFile(file.physicalFilename.c_str());
            if(file.fd > 0){
                return;
            }
        }
    }

    //打开请求的文件
    void RapidHttpServlet::openRequestFile(){
        //contextConfig->name.c_str(), subpath, strlen(subpath)
        file.filename.clear();
        file.physicalFilename.clear();         
        file.filename.append("/").append(subpath);
        file.physicalFilename.append(contextConfig->docBase).append(file.filename);
        LOG_DEBUG("file.filename:%s", file.filename.c_str());
        LOG_DEBUG("file.physicalFilename:%s", file.physicalFilename.c_str());
        openFile(file.physicalFilename.c_str());
    }

    void RapidHttpServlet::openFile(const char* filename){
        
        if(fileCached.enableCache()){
            file.fd = fileCached.openFile(file.stat, filename);
            LOG_DEBUG("file.fd:%d", file.fd );
            if(file.fd >= 0){
                return;
            }
        }
        
        if(stat(filename, &file.stat)!=0){
            LOG_DEBUG("file not exist! errno:%d", errno);
            return;
        }

        if(S_ISDIR(file.stat.st_mode)){
            LOG_DEBUG("is dir, file.stat.st_size:%d", file.stat.st_size);
            return;
        }

        //serverConfig->
        LOG_DEBUG("file.stat.st_size:%d", file.stat.st_size);
        if(fileCached.enableCache(file.stat.st_size)){
            //向父进程发送cache文件消息
            HttpProcess* process = httpHandler->getHttpProcess();
            if(process){
                LOG_DEBUG("filename:%s, st_size:%ld", file.filename.c_str(), file.stat.st_size);
                process->sendMessage(MSG_TYPE_CACHE_FILE, (void*)filename, strlen(filename)+1);
            }else{
                LOG_WARN("process is NULL");   
            }
        }
        
        //打开文件
        file.fd = ::open(filename, O_RDONLY | O_NONBLOCK);
        if(file.fd < 0){
            LOG_DEBUG("open file error, errno:%d", errno);
        }

    }

    const char* RapidHttpServlet::getExpandName(std::string* filename){
        int index = filename->rfind('.');
        LOG_DEBUG("index:%d", index);
        if(index >= 0){
        return filename->c_str()+index+1;
        }
        return NULL;
    }

    ContentTypeConfig* RapidHttpServlet::getContentTypeConfig(const char* filetype){
        if(!filetype){
            filetype = "*";
        }
        LOG_DEBUG("filetype:%s", filetype);
        ContextConfig::ContentTypeConfigMap::iterator cttcit = contextConfig->contentTypeConfigMap.find(filetype);
        if(cttcit != contextConfig->contentTypeConfigMap.end()){
            LOG_DEBUG("contentType:%s", cttcit->second->contentType.c_str());
            return cttcit->second;
        }        
        return NULL;
    }
    
}





